package com.hondee.fuzzyquery.query;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

import com.hondee.fuzzyquery.entity.Entity;
import com.hondee.fuzzyquery.entity.EntityCollections;
import com.hondee.fuzzyquery.entity.access.IEntityAccess;
import com.hondee.fuzzyquery.entity.access.QueryOrder;
import com.hondee.fuzzyquery.query.targetdefinition.ITargetResource;
import com.hondee.fuzzyquery.utils.StringUtil;

public class DefaultFuzzyQuery implements IFuzzyQuery {
	
	private final List<IQueryTarget> queryTarget;
	
	private ExecutorService sc;
	
	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	public DefaultFuzzyQuery(ITargetResource targetResource){
		List<IQueryTarget> targets = targetResource.getTargets();
		if(targets==null){
			queryTarget = new ArrayList<>();
		}else{
			queryTarget = Collections.unmodifiableList(targets);
		}
		sc = Executors.newCachedThreadPool(new ThreadFactory() {
			
			@Override
			public Thread newThread(Runnable r) {
				Thread t = new Thread(r);
				t.setDaemon(true);
				return t;
			}
		});
	}

	@Override
	public EntityCollections query(String queryStringInput,QueryOrder queryOrder,Integer pageIndex,Integer pageSize) {
		if(StringUtil.isNullOrEmpty(queryStringInput)){
			return null;
		}
		CountDownLatch countdownLatch = new CountDownLatch(queryTarget.size());
		EntityCollections results = new EntityCollections();
		
		for(IQueryTarget target : queryTarget){
			sc.execute(new QueryRunner(EntityAccessFactory.getAccess(target, pageIndex, pageSize, queryStringInput, jdbcTemplate)
					,results
					,countdownLatch));
		}
		try {
			countdownLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return results;
	}

	@Override
	public Entity<?> querySingleTarget(String targetName, String queryString, QueryOrder queryOrder, Integer pageIndex,
			Integer pageSize) {
		IQueryTarget _target = null;
		for(IQueryTarget target : queryTarget){
			if(target.getIdentity().equals(targetName)){
				_target = target;
			}
		}
		if(_target==null){
			throw new RuntimeException("target not exists.");
		}
		
		IEntityAccess access = EntityAccessFactory.getAccess(_target, pageIndex, pageSize, queryString, jdbcTemplate);
		return access.access();
		
	}

	@Override
	public List<IQueryTarget> queryTarget() {
		return queryTarget;
	}
}
